Add support for cdylib crate types
authorAlex Crichton <alex@alexcrichton.com>
Fri, 20 May 2016 23:34:50 +0000 (16:34 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Sun, 12 Jun 2016 10:46:53 +0000 (03:46 -0700)
And while we're at it this also extends support for all future crate types
assuming that they aren't linkable by default.

src/cargo/core/manifest.rs
src/cargo/ops/cargo_clean.rs
src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/fingerprint.rs
src/cargo/ops/cargo_rustc/mod.rs
src/cargo/util/toml.rs
tests/bad-config.rs

index 00639978c4817bbee7df084267e011a97a2d163f..d7133878d5853255e3ef5a3c8d7615006bc7c126 100644 (file)
@@ -6,7 +6,6 @@ use rustc_serialize::{Encoder, Encodable};
 
 use core::{Dependency, PackageId, PackageIdSpec, Summary};
 use core::package_id::Metadata;
-use util::{CargoResult, human};
 
 /// Contains all the information about a package, as loaded from a Cargo.toml.
 #[derive(Clone, Debug)]
@@ -44,33 +43,40 @@ pub struct ManifestMetadata {
     pub documentation: Option<String>,  // url
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, RustcEncodable, Copy)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum LibKind {
     Lib,
     Rlib,
     Dylib,
-    StaticLib
+    Other(String),
 }
 
 impl LibKind {
-    pub fn from_str(string: &str) -> CargoResult<LibKind> {
+    pub fn from_str(string: &str) -> LibKind {
         match string {
-            "lib" => Ok(LibKind::Lib),
-            "rlib" => Ok(LibKind::Rlib),
-            "dylib" => Ok(LibKind::Dylib),
-            "staticlib" => Ok(LibKind::StaticLib),
-            _ => Err(human(format!("crate-type \"{}\" was not one of lib|rlib|dylib|staticlib",
-                                   string)))
+            "lib" => LibKind::Lib,
+            "rlib" => LibKind::Rlib,
+            "dylib" => LibKind::Dylib,
+            s => LibKind::Other(s.to_string()),
         }
     }
 
     /// Returns the argument suitable for `--crate-type` to pass to rustc.
-    pub fn crate_type(&self) -> &'static str {
+    pub fn crate_type(&self) -> &str {
         match *self {
             LibKind::Lib => "lib",
             LibKind::Rlib => "rlib",
             LibKind::Dylib => "dylib",
-            LibKind::StaticLib => "staticlib"
+            LibKind::Other(ref s) => s,
+        }
+    }
+
+    pub fn linkable(&self) -> bool {
+        match *self {
+            LibKind::Lib |
+            LibKind::Rlib |
+            LibKind::Dylib => true,
+            LibKind::Other(..) => false,
         }
     }
 }
@@ -335,12 +341,7 @@ impl Target {
     pub fn linkable(&self) -> bool {
         match self.kind {
             TargetKind::Lib(ref kinds) => {
-                kinds.iter().any(|k| {
-                    match *k {
-                        LibKind::Lib | LibKind::Rlib | LibKind::Dylib => true,
-                        LibKind::StaticLib => false,
-                    }
-                })
+                kinds.iter().any(|k| k.linkable())
             }
             _ => false
         }
@@ -353,7 +354,7 @@ impl Target {
     pub fn is_custom_build(&self) -> bool { self.kind == TargetKind::CustomBuild }
 
     /// Returns the arguments suitable for `--crate-type` to pass to rustc.
-    pub fn rustc_crate_types(&self) -> Vec<&'static str> {
+    pub fn rustc_crate_types(&self) -> Vec<&str> {
         match self.kind {
             TargetKind::Lib(ref kinds) => {
                 kinds.iter().map(|kind| kind.crate_type()).collect()
@@ -368,7 +369,11 @@ impl Target {
 
     pub fn can_lto(&self) -> bool {
         match self.kind {
-            TargetKind::Lib(ref v) => *v == [LibKind::StaticLib],
+            TargetKind::Lib(ref v) => {
+                !v.contains(&LibKind::Rlib) &&
+                    !v.contains(&LibKind::Dylib) &&
+                    !v.contains(&LibKind::Lib)
+            }
             _ => true,
         }
     }
index 8b8f3cae90a126d28df9e5f905449029a326fdd5..1c70176af1d11c4bbd1307360ce241aaab740cb9 100644 (file)
@@ -42,23 +42,20 @@ pub fn clean(manifest_path: &Path, opts: &CleanOptions) -> CargoResult<()> {
         None => None,
     };
 
-    let cx = try!(Context::new(&resolve, &packages, opts.config,
-                               host_layout, target_layout,
-                               BuildConfig::default(),
-                               root.manifest().profiles()));
+    let mut cx = try!(Context::new(&resolve, &packages, opts.config,
+                                   host_layout, target_layout,
+                                   BuildConfig::default(),
+                                   root.manifest().profiles()));
+    let mut units = Vec::new();
 
-    // resolve package specs and remove the corresponding packages
     for spec in opts.spec {
         // Translate the spec to a Package
         let pkgid = try!(resolve.query(spec));
         let pkg = try!(packages.get(&pkgid));
 
-        // And finally, clean everything out!
+        // Generate all relevant `Unit` targets for this package
         for target in pkg.targets() {
             for kind in [Kind::Host, Kind::Target].iter() {
-                let layout = cx.layout(&pkg, *kind);
-                try!(rm_rf(&layout.proxy().fingerprint(&pkg)));
-                try!(rm_rf(&layout.build(&pkg)));
                 let Profiles {
                     ref release, ref dev, ref test, ref bench, ref doc,
                     ref custom_build, ref test_deps, ref bench_deps,
@@ -66,21 +63,30 @@ pub fn clean(manifest_path: &Path, opts: &CleanOptions) -> CargoResult<()> {
                 let profiles = [release, dev, test, bench, doc, custom_build,
                                 test_deps, bench_deps];
                 for profile in profiles.iter() {
-                    let unit = Unit {
+                    units.push(Unit {
                         pkg: &pkg,
                         target: target,
                         profile: profile,
                         kind: *kind,
-                    };
-                    let root = cx.out_dir(&unit);
-                    for filename in try!(cx.target_filenames(&unit)).iter() {
-                        try!(rm_rf(&root.join(&filename)));
-                    }
+                    });
                 }
             }
         }
     }
 
+    try!(cx.probe_target_info(&units));
+
+    for unit in units.iter() {
+        let layout = cx.layout(&unit.pkg, unit.kind);
+        try!(rm_rf(&layout.proxy().fingerprint(&unit.pkg)));
+        try!(rm_rf(&layout.build(&unit.pkg)));
+
+        let root = cx.out_dir(&unit);
+        for (filename, _) in try!(cx.target_filenames(&unit)) {
+            try!(rm_rf(&root.join(&filename)));
+        }
+    }
+
     Ok(())
 }
 
index bd5a76ba7a5b93933470d08ea1806c4fe2d57766..6eb5ecca92ca4831211b706f0bc55c5b4b831385 100644 (file)
@@ -1,13 +1,12 @@
-use std::collections::{HashSet, HashMap};
+use std::collections::{HashSet, HashMap, BTreeSet};
 use std::env;
 use std::path::{Path, PathBuf};
 use std::str::{self, FromStr};
 use std::sync::Arc;
 
-use regex::Regex;
 
 use core::{Package, PackageId, PackageSet, Resolve, Target, Profile};
-use core::{TargetKind, LibKind, Profiles, Metadata, Dependency};
+use core::{TargetKind, Profiles, Metadata, Dependency};
 use core::dependency::Kind as DepKind;
 use util::{self, CargoResult, ChainError, internal, Config, profile, Cfg, human};
 
@@ -49,11 +48,9 @@ pub struct Context<'a, 'cfg: 'a> {
     profiles: &'a Profiles,
 }
 
-#[derive(Clone)]
+#[derive(Clone, Default)]
 struct TargetInfo {
-    dylib: Option<(String, String)>,
-    staticlib: Option<(String, String)>,
-    exe: String,
+    crate_types: HashMap<String, Option<(String, String)>>,
     cfg: Option<Vec<Cfg>>,
 }
 
@@ -67,12 +64,6 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
                profiles: &'a Profiles) -> CargoResult<Context<'a, 'cfg>> {
         let target = build_config.requested_target.clone();
         let target = target.as_ref().map(|s| &s[..]);
-        let target_info = try!(Context::target_info(target, config, &build_config));
-        let host_info = if build_config.requested_target.is_none() {
-            target_info.clone()
-        } else {
-            try!(Context::target_info(None, config, &build_config))
-        };
         let target_triple = target.unwrap_or_else(|| {
             &config.rustc_info().host[..]
         }).to_string();
@@ -86,8 +77,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
             resolve: resolve,
             packages: packages,
             config: config,
-            target_info: target_info,
-            host_info: host_info,
+            target_info: TargetInfo::default(),
+            host_info: TargetInfo::default(),
             compilation: Compilation::new(config),
             build_state: Arc::new(BuildState::new(&build_config)),
             build_config: build_config,
@@ -101,25 +92,87 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         })
     }
 
-    /// Run `rustc` to discover the dylib prefix/suffix for the target
-    /// specified as well as the exe suffix
-    fn target_info(target: Option<&str>,
-                   cfg: &Config,
-                   build_config: &BuildConfig)
-                   -> CargoResult<TargetInfo> {
-        let kind = if target.is_none() {Kind::Host} else {Kind::Target};
-        let mut process = util::process(cfg.rustc());
+    /// Prepare this context, ensuring that all filesystem directories are in
+    /// place.
+    pub fn prepare(&mut self, root: &Package) -> CargoResult<()> {
+        let _p = profile::start("preparing layout");
+
+        try!(self.host.prepare().chain_error(|| {
+            internal(format!("couldn't prepare build directories"))
+        }));
+        match self.target {
+            Some(ref mut target) => {
+                try!(target.prepare().chain_error(|| {
+                    internal(format!("couldn't prepare build directories"))
+                }));
+            }
+            None => {}
+        }
+
+        self.compilation.root_output =
+                self.layout(root, Kind::Target).proxy().dest().to_path_buf();
+        self.compilation.deps_output =
+                self.layout(root, Kind::Target).proxy().deps().to_path_buf();
+        Ok(())
+    }
+
+    /// Ensure that we've collected all target-specific information to compile
+    /// all the units mentioned in `units`.
+    pub fn probe_target_info(&mut self, units: &[Unit<'a>]) -> CargoResult<()> {
+        let mut crate_types = BTreeSet::new();
+        // pre-fill with `bin` for learning about tests (nothing may be
+        // explicitly `bin`) as well as `rlib` as it's the coalesced version of
+        // `lib` in the compiler and we're not sure which we'll see.
+        crate_types.insert("bin".to_string());
+        crate_types.insert("rlib".to_string());
+        for unit in units {
+            try!(self.visit_crate_type(unit, &mut crate_types));
+        }
+        try!(self.probe_target_info_kind(&crate_types, Kind::Target));
+        if self.build_config.requested_target.is_none() {
+            self.host_info = self.target_info.clone();
+        } else {
+            try!(self.probe_target_info_kind(&crate_types, Kind::Host));
+        }
+        Ok(())
+    }
+
+    fn visit_crate_type(&self,
+                        unit: &Unit<'a>,
+                        crate_types: &mut BTreeSet<String>)
+                        -> CargoResult<()> {
+        for target in unit.pkg.manifest().targets() {
+            crate_types.extend(target.rustc_crate_types().iter().map(|s| {
+                if *s == "lib" {
+                    "rlib".to_string()
+                } else {
+                    s.to_string()
+                }
+            }));
+        }
+        for dep in try!(self.dep_targets(&unit)) {
+            try!(self.visit_crate_type(&dep, crate_types));
+        }
+        Ok(())
+    }
+
+    fn probe_target_info_kind(&mut self,
+                              crate_types: &BTreeSet<String>,
+                              kind: Kind)
+                              -> CargoResult<()> {
+        let mut process = util::process(self.config.rustc());
         process.arg("-")
                .arg("--crate-name").arg("_")
-               .arg("--crate-type").arg("dylib")
-               .arg("--crate-type").arg("staticlib")
-               .arg("--crate-type").arg("bin")
                .arg("--print=file-names")
-               .args(&try!(rustflags_args(cfg, build_config, kind)))
+               .args(&try!(rustflags_args(self.config, &self.build_config, kind)))
                .env_remove("RUST_LOG");
-        if let Some(s) = target {
-            process.arg("--target").arg(s);
-        };
+
+        for crate_type in crate_types {
+            process.arg("--crate-type").arg(crate_type);
+        }
+        if kind == Kind::Target {
+            process.arg("--target").arg(&self.target_triple);
+        }
 
         let mut with_cfg = process.clone();
         with_cfg.arg("--print=cfg");
@@ -136,34 +189,31 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         let error = str::from_utf8(&output.stderr).unwrap();
         let output = str::from_utf8(&output.stdout).unwrap();
         let mut lines = output.lines();
-        let nodylib = Regex::new("unsupported crate type.*dylib").unwrap();
-        let nostaticlib = Regex::new("unsupported crate type.*staticlib").unwrap();
-        let nobin = Regex::new("unsupported crate type.*bin").unwrap();
-        let dylib = if nodylib.is_match(error) {
-            None
-        } else {
-            let dylib_parts: Vec<&str> = lines.next().unwrap().trim()
-                                              .split('_').collect();
-            assert!(dylib_parts.len() == 2,
-                    "rustc --print-file-name output has changed");
-            Some((dylib_parts[0].to_string(), dylib_parts[1].to_string()))
-        };
-        let staticlib = if nostaticlib.is_match(error) {
-            None
-        } else {
-            let staticlib_parts: Vec<&str> = lines.next().unwrap().trim()
-                                              .split('_').collect();
-            assert!(staticlib_parts.len() == 2,
-                    "rustc --print-file-name output has changed");
-            Some((staticlib_parts[0].to_string(), staticlib_parts[1].to_string()))
-        };
-
-        let exe = if nobin.is_match(error) {
-            String::new()
-        } else {
-            lines.next().unwrap().trim()
-                 .split('_').skip(1).next().unwrap().to_string()
-        };
+        let mut map = HashMap::new();
+        for crate_type in crate_types {
+            let not_supported = error.lines().any(|line| {
+                line.contains("unsupported crate type") &&
+                    line.contains(crate_type)
+            });
+            if not_supported {
+                map.insert(crate_type.to_string(), None);
+                continue
+            }
+            let line = match lines.next() {
+                Some(line) => line,
+                None => bail!("malformed output when learning about \
+                               target-specific information from rustc"),
+            };
+            let mut parts = line.trim().split('_');
+            let prefix = parts.next().unwrap();
+            let suffix = match parts.next() {
+                Some(part) => part,
+                None => bail!("output of --print=file-names has changed in \
+                               the compiler, cannot parse"),
+            };
+            map.insert(crate_type.to_string(),
+                       Some((prefix.to_string(), suffix.to_string())));
+        }
 
         let cfg = if has_cfg {
             Some(try!(lines.map(Cfg::from_str).collect()))
@@ -171,36 +221,12 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
             None
         };
 
-        Ok(TargetInfo {
-            dylib: dylib,
-            staticlib: staticlib,
-            exe: exe,
-            cfg: cfg,
-        })
-    }
-
-    /// Prepare this context, ensuring that all filesystem directories are in
-    /// place.
-    pub fn prepare(&mut self, root: &Package) -> CargoResult<()> {
-        let _p = profile::start("preparing layout");
-
-        try!(self.host.prepare().chain_error(|| {
-            internal(format!("couldn't prepare build directories"))
-        }));
-        match self.target {
-            Some(ref mut target) => {
-                try!(target.prepare().chain_error(|| {
-                    internal(format!("couldn't prepare build directories"))
-                }));
-            }
-            None => {}
-        }
-
-        self.compilation.root_output =
-                self.layout(root, Kind::Target).proxy().dest().to_path_buf();
-        self.compilation.deps_output =
-                self.layout(root, Kind::Target).proxy().deps().to_path_buf();
-
+        let info = match kind {
+            Kind::Target => &mut self.target_info,
+            Kind::Host => &mut self.host_info,
+        };
+        info.crate_types = map;
+        info.cfg = cfg;
         Ok(())
     }
 
@@ -225,38 +251,6 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         }
     }
 
-    /// Return the (prefix, suffix) pair for dynamic libraries.
-    ///
-    /// If `plugin` is true, the pair corresponds to the host platform,
-    /// otherwise it corresponds to the target platform.
-    fn dylib(&self, kind: Kind) -> CargoResult<(&str, &str)> {
-        let (triple, pair) = if kind == Kind::Host {
-            (&self.config.rustc_info().host, &self.host_info.dylib)
-        } else {
-            (&self.target_triple, &self.target_info.dylib)
-        };
-        match *pair {
-            None => bail!("dylib outputs are not supported for {}", triple),
-            Some((ref s1, ref s2)) => Ok((s1, s2)),
-        }
-    }
-
-    /// Return the (prefix, suffix) pair for static libraries.
-    ///
-    /// If `plugin` is true, the pair corresponds to the host platform,
-    /// otherwise it corresponds to the target platform.
-    pub fn staticlib(&self, kind: Kind) -> CargoResult<(&str, &str)> {
-        let (triple, pair) = if kind == Kind::Host {
-            (&self.config.rustc_info().host, &self.host_info.staticlib)
-        } else {
-            (&self.target_triple, &self.target_info.staticlib)
-        };
-        match *pair {
-            None => bail!("staticlib outputs are not supported for {}", triple),
-            Some((ref s1, ref s2)) => Ok((s1, s2)),
-        }
-    }
-
     /// Return the target triple which this context is targeting.
     pub fn target_triple(&self) -> &str {
         &self.target_triple
@@ -304,56 +298,67 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
     }
 
     /// Return the filenames that the given target for the given profile will
-    /// generate.
-    pub fn target_filenames(&self, unit: &Unit) -> CargoResult<Vec<String>> {
+    /// generate, along with whether you can link against that file (e.g. it's a
+    /// library).
+    pub fn target_filenames(&self, unit: &Unit)
+                            -> CargoResult<Vec<(String, bool)>> {
         let stem = self.file_stem(unit);
-        let suffix = if unit.target.for_host() {
-            &self.host_info.exe
+        let info = if unit.target.for_host() {
+            &self.host_info
         } else {
-            &self.target_info.exe
+            &self.target_info
         };
 
         let mut ret = Vec::new();
-        match *unit.target.kind() {
-            TargetKind::Example |
-            TargetKind::Bin |
-            TargetKind::CustomBuild |
-            TargetKind::Bench |
-            TargetKind::Test => {
-                ret.push(format!("{}{}", stem, suffix));
-            }
-            TargetKind::Lib(..) if unit.profile.test => {
-                ret.push(format!("{}{}", stem, suffix));
-            }
-            TargetKind::Lib(ref libs) => {
-                for lib in libs {
-                    match *lib {
-                        LibKind::Dylib => {
-                            if let Ok((prefix, suffix)) = self.dylib(unit.kind) {
-                                ret.push(format!("{}{}{}", prefix, stem, suffix));
-                            }
-                        }
-                        LibKind::Lib |
-                        LibKind::Rlib => ret.push(format!("lib{}.rlib", stem)),
-                        LibKind::StaticLib => {
-                            if let Ok((prefix, suffix)) = self.staticlib(unit.kind) {
-                                ret.push(format!("{}{}{}", prefix, stem, suffix));
-                            }
-                        }
+        let mut unsupported = Vec::new();
+        {
+            let mut add = |crate_type: &str, linkable: bool| -> CargoResult<()> {
+                let crate_type = if crate_type == "lib" {"rlib"} else {crate_type};
+                match info.crate_types.get(crate_type) {
+                    Some(&Some((ref prefix, ref suffix))) => {
+                        ret.push((format!("{}{}{}", prefix, stem, suffix),
+                                  linkable));
+                        Ok(())
+                    }
+                    // not supported, don't worry about it
+                    Some(&None) => {
+                        unsupported.push(crate_type.to_string());
+                        Ok(())
                     }
+                    None => {
+                        bail!("failed to learn about crate-type `{}` early on",
+                              crate_type)
+                    }
+                }
+            };
+            match *unit.target.kind() {
+                TargetKind::Example |
+                TargetKind::Bin |
+                TargetKind::CustomBuild |
+                TargetKind::Bench |
+                TargetKind::Test => {
+                    try!(add("bin", false));
                 }
-                if ret.is_empty() {
-                    if libs.contains(&LibKind::Dylib) {
-                        bail!("cannot produce dylib for `{}` as the target `{}` \
-                               does not support dynamic libraries",
-                              unit.pkg, self.target_triple)
+                TargetKind::Lib(..) if unit.profile.test => {
+                    try!(add("bin", false));
+                }
+                TargetKind::Lib(ref libs) => {
+                    for lib in libs {
+                        try!(add(lib.crate_type(), lib.linkable()));
                     }
-                    bail!("cannot compile `{}` as the target `{}` does not \
-                           support any of the output crate types",
-                          unit.pkg, self.target_triple);
                 }
             }
         }
+        if ret.is_empty() {
+            if unsupported.len() > 0 {
+                bail!("cannot produce {} for `{}` as the target `{}` \
+                       does not support these crate types",
+                      unsupported.join(", "), unit.pkg, self.target_triple)
+            }
+            bail!("cannot compile `{}` as the target `{}` does not \
+                   support any of the output crate types",
+                  unit.pkg, self.target_triple);
+        }
         Ok(ret)
     }
 
index 042e223b3cb7deb8e765d8812e47121e877e7c1f..437474c498e5ea28d0699769aacafb9458b87019 100644 (file)
@@ -63,7 +63,7 @@ pub fn prepare_target<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,
         missing_outputs = !root.join(unit.target.crate_name())
                                .join("index.html").exists();
     } else {
-        for filename in try!(cx.target_filenames(unit)).iter() {
+        for (filename, _) in try!(cx.target_filenames(unit)) {
             missing_outputs |= fs::metadata(root.join(filename)).is_err();
         }
     }
index cc40730a84c88ad02e77fd6ce737b78e1a3bd9d8..91626dccc99ce9a6853a09e642670d441b84215b 100644 (file)
@@ -96,6 +96,7 @@ pub fn compile_targets<'a, 'cfg: 'a>(pkg_targets: &'a PackagesToBuild<'a>,
     let mut queue = JobQueue::new(&cx);
 
     try!(cx.prepare(root));
+    try!(cx.probe_target_info(&units));
     try!(custom_build::build_map(&mut cx, &units));
 
     for unit in units.iter() {
@@ -117,7 +118,7 @@ pub fn compile_targets<'a, 'cfg: 'a>(pkg_targets: &'a PackagesToBuild<'a>,
           .or_insert(Vec::new())
           .push(("OUT_DIR".to_string(), out_dir));
 
-        for filename in try!(cx.target_filenames(unit)).iter() {
+        for (filename, _linkable) in try!(cx.target_filenames(unit)) {
             let dst = cx.out_dir(unit).join(filename);
             if unit.profile.test {
                 cx.compilation.tests.push((unit.pkg.clone(),
@@ -142,7 +143,7 @@ pub fn compile_targets<'a, 'cfg: 'a>(pkg_targets: &'a PackagesToBuild<'a>,
                 }
 
                 let v = try!(cx.target_filenames(unit));
-                let v = v.into_iter().map(|f| {
+                let v = v.into_iter().map(|(f, _)| {
                     (unit.target.clone(), cx.out_dir(unit).join(f))
                 }).collect::<Vec<_>>();
                 cx.compilation.libraries.insert(pkgid.clone(), v);
@@ -264,7 +265,7 @@ fn rustc(cx: &mut Context, unit: &Unit) -> CargoResult<Work> {
 
         // FIXME(rust-lang/rust#18913): we probably shouldn't have to do
         //                              this manually
-        for filename in filenames.iter() {
+        for &(ref filename, _linkable) in filenames.iter() {
             let dst = root.join(filename);
             if fs::metadata(&dst).is_ok() {
                 try!(fs::remove_file(&dst));
@@ -280,7 +281,7 @@ fn rustc(cx: &mut Context, unit: &Unit) -> CargoResult<Work> {
         }));
 
         if do_rename && real_name != crate_name {
-            let dst = root.join(&filenames[0]);
+            let dst = root.join(&filenames[0].0);
             let src = dst.with_file_name(dst.file_name().unwrap()
                                             .to_str().unwrap()
                                             .replace(&real_name, &crate_name));
@@ -587,11 +588,9 @@ fn build_deps_args(cmd: &mut CommandPrototype, cx: &Context, unit: &Unit)
                -> CargoResult<()> {
         let layout = cx.layout(unit.pkg, unit.kind);
 
-        for filename in try!(cx.target_filenames(unit)) {
-            if let Ok((prefix, suffix)) = cx.staticlib(unit.kind) {
-                if filename.starts_with(prefix) && filename.ends_with(suffix) {
-                    continue
-                }
+        for (filename, linkable) in try!(cx.target_filenames(unit)) {
+            if !linkable {
+                continue
             }
             let mut v = OsString::new();
             v.push(&unit.target.crate_name());
index 82ea4533aca521587b5c4c10883a6f03563a2c80..04991a71dae88ee8607cb40f2ad4f33668d6e6d4 100644 (file)
@@ -495,8 +495,7 @@ impl TomlManifest {
                                 &examples,
                                 &tests,
                                 &benches,
-                                &metadata,
-                                &mut warnings);
+                                &metadata);
 
         if targets.is_empty() {
             debug!("manifest has no build targets");
@@ -867,8 +866,7 @@ fn normalize(lib: &Option<TomlLibTarget>,
              examples: &[TomlExampleTarget],
              tests: &[TomlTestTarget],
              benches: &[TomlBenchTarget],
-             metadata: &Metadata,
-             warnings: &mut Vec<String>) -> Vec<Target> {
+             metadata: &Metadata) -> Vec<Target> {
     fn configure(toml: &TomlTarget, target: &mut Target) {
         let t2 = target.clone();
         target.set_tested(toml.test.unwrap_or(t2.tested()))
@@ -881,23 +879,12 @@ fn normalize(lib: &Option<TomlLibTarget>,
 
     fn lib_target(dst: &mut Vec<Target>,
                   l: &TomlLibTarget,
-                  metadata: &Metadata,
-                  warnings: &mut Vec<String>) {
+                  metadata: &Metadata) {
         let path = l.path.clone().unwrap_or(
             PathValue::Path(Path::new("src").join(&format!("{}.rs", l.name())))
         );
         let crate_types = match l.crate_type.clone() {
-            Some(kinds) => {
-                // For now, merely warn about invalid crate types.
-                // In the future, it might be nice to make them errors.
-                kinds.iter().filter_map(|s| {
-                    let kind = LibKind::from_str(s);
-                    if let Err(ref error) = kind {
-                        warnings.push(error.to_string());
-                    }
-                    kind.ok()
-                }).collect()
-            }
+            Some(kinds) => kinds.iter().map(|s| LibKind::from_str(s)).collect(),
             None => {
                 vec![ if l.plugin == Some(true) {LibKind::Dylib}
                       else {LibKind::Lib} ]
@@ -992,7 +979,7 @@ fn normalize(lib: &Option<TomlLibTarget>,
     let mut ret = Vec::new();
 
     if let Some(ref lib) = *lib {
-        lib_target(&mut ret, lib, metadata, warnings);
+        lib_target(&mut ret, lib, metadata);
         bin_targets(&mut ret, bins,
                     &mut |bin| Path::new("src").join("bin")
                                    .join(&format!("{}.rs", bin.name())));
index b88ea2f6bfe4125ab6b7e3023c3603411daac204..d456d1f21f34ece41ff456d95759c9bbf20be49b 100644 (file)
@@ -271,10 +271,8 @@ fn bad_crate_type() {
     .file("src/lib.rs", "");
 
     assert_that(foo.cargo_process("build").arg("-v"),
-                execs().with_status(0).with_stderr("\
-warning: crate-type \"bad_type\" was not one of lib|rlib|dylib|staticlib
-[COMPILING] foo v0.0.0 (file:///[..])
-[RUNNING] `rustc [..] --crate-type rlib [..]`
+                execs().with_status(101).with_stderr_contains("\
+error: failed to run `rustc` to learn about target-specific information
 "));
 }